package com.woniu.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniu.exception.LXLGException;
import com.woniu.exception.LXLGException;
import com.woniu.product.client.param.SearchAllParam;
import com.woniu.product.common.ProductResultCode;
import com.woniu.product.client.param.AddProductParam;
import com.woniu.product.client.param.AddPropParam;
import com.woniu.product.common.ProductResultCode;
import com.woniu.product.infra.es.model.SpuEsModel;
import com.woniu.product.infra.es.SPUEsRepository;
import com.woniu.product.client.result.PageSpuResultInfo;
import com.woniu.product.infra.es.model.SpuEsModel;
import com.woniu.product.infra.model.*;
import com.woniu.product.infra.mapper.SpuMapper;
import com.woniu.product.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.product.service.dto.*;
import com.woniu.product.service.form.AddProductForm;
import com.woniu.product.service.form.ListCrowdProductForm;
import com.woniu.result.Result;
import com.woniu.util.DateUtil;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 标准产品单元 服务实现类
 * </p>
 *
 * @author Lucas
 * @since 2022-11-26
 */
@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {

    @Resource
    private PropService propService;
    @Resource
    private CategoryService categoryService;

    @Resource
    private PropValueService propValueService;
    @Resource
    private LxlgFootprintService lxlgFootprintService;
    @Resource
    private ElasticsearchOperations eo;


    /**
     * 根据spuId查询Spu详情
     *
     * @param spuId
     * @return
     */
    @Override
    public SpuDto querySpuInfo(Integer spuId,Integer userId) {
        //查询spu
        Spu spu = getById(spuId);
        SpuDto spuDto = BeanUtil.copyProperties(spu, SpuDto.class);
        //查询对应的属性
        QueryWrapper<Prop> qw = new QueryWrapper<>();
        qw.eq("spu_id", spuId);
        List<Prop> props = propService.list(qw);

        //插入足迹
        LxlgFootprint fp = new LxlgFootprint();
        fp.setSpuId(spuId);
        fp.setBrowseTime(DateUtil.parseDateLong());
        fp.setUserId(userId);
        fp.setSpuName(spu.getSpuName());
        lxlgFootprintService.save(fp);

        if (props.size() == 0) return spuDto;
        //查询属性对应的属性值
        List<PropDto> propDtoList = new ArrayList<>();
        for (Prop prop : props) {
            QueryWrapper<PropValue> qw1 = new QueryWrapper<>();
            qw1.eq("prop_id", prop.getPropId());
            List<PropValue> propValues = propValueService.list(qw1);
            PropDto propDto = BeanUtil.copyProperties(prop, PropDto.class);
            List<PropValueDto> propValueDtos = BeanUtil.copyToList(propValues, PropValueDto.class);
            propDto.setPropValues(propValueDtos);
            propDtoList.add(propDto);
        }
        spuDto.setPropList(propDtoList);
        return spuDto;
    }

    /**
     * 新增商品spu
     *
     * @param addProductForm
     */
    @Override
    public void addProduct(AddProductForm addProductForm) {
        Spu spu = BeanUtil.copyProperties(addProductForm, Spu.class);
        Category category = categoryService.getById(addProductForm.getCategoryId());
        spu.setCategoryName(category.getCategoryName());
        spu.setCreateTime(DateUtil.parseDateLong());
        spu.setSpuStatus("OFF_SALE");
        save(spu);
        for (AddPropParam addpROParam : addProductForm.getAddpROParams()) {
            Prop prop = BeanUtil.copyProperties(addpROParam, Prop.class);
            prop.setSpuId(spu.getSpuId());
            propService.save(prop);
            List<PropValue> propValues = BeanUtil.copyToList(addpROParam.getAddPropValueParams(), PropValue.class);
            for (PropValue propValue : propValues) {
                propValue.setPropId(prop.getPropId());
                propValueService.save(propValue);
            }
        }
    }

    @Override
    public Result downSPU(Integer spuId) {
        Spu spu = getById(spuId);
        if (spu.getSpuStatus().equals("OFF_SALE")) {
            throw new LXLGException("商品已经下架，请勿重复操作", 401);
        }
        //修改数据库
        spu.setSpuStatus("OFF_SALE");
        updateById(spu);
//        上传es
        SpuEsModel spuEsModel = BeanUtil.copyProperties(spu, SpuEsModel.class);
        eo.delete(spuEsModel);
        return Result.getInstance().setCode(200).setMsg("商品下架成功");
    }

    @Override
    public Result upSPU(Integer spuId) {
        Spu spu = getById(spuId);
        if (spu.getSpuStatus().equals("ON_SALE")) {
            throw new LXLGException("商品已经上架，请勿重复操作", 402);
        }
        //修改数据库状态
        spu.setSpuStatus("ON_SALE");
        updateById(spu);
        SpuEsModel spuEsModel = BeanUtil.copyProperties(spu, SpuEsModel.class);
        //上传es
        eo.save(spuEsModel);
        return Result.getInstance().setCode(200).setMsg("商品上架成功");
    }

    @Override
    public Result delSPU(Integer spuId) {
        Spu spu = getById(spuId);
        if (spu.getSpuStatus().equals("ON_SALE")) {
            throw new LXLGException("请先下架商品，才能进行删除", 401);
        }
        if (spu.getSpuStatus().equals("DELETE")) {
            throw new LXLGException("商品已经删除，请勿重复操作", 403);
        }
        spu.setSpuStatus("DELETE");
        updateById(spu);
        return Result.getInstance().setCode(200).setMsg("商品删除成功");
    }


    @Override
    public Result search(SearchAllParam searchAllParam) {
        NativeSearchQueryBuilder nsqb = new NativeSearchQueryBuilder();
        BoolQueryBuilder bqb1 = new BoolQueryBuilder();
        BoolQueryBuilder bqb2 = new BoolQueryBuilder();
        //关键字
        if (searchAllParam.getKeyword() != null && !"".equals(searchAllParam.getKeyword().trim()) && searchAllParam.getKeyword().length() > 0) {

            bqb2.should().add(new MatchQueryBuilder("spuName", searchAllParam.getKeyword()));
            bqb2.should().add(new MatchQueryBuilder("categoryName", searchAllParam.getKeyword()));
            bqb2.should().add(new MatchQueryBuilder("introduction", searchAllParam.getKeyword()));
            bqb1.must().add(bqb2);
        }
        //价格区间
        RangeQueryBuilder rqb = null;
        if (searchAllParam.getStartPrice() != null && searchAllParam.getEndPrice() != null) {
            rqb = new RangeQueryBuilder("minPrice");
            rqb.gte(searchAllParam.getStartPrice());
            rqb.lte(searchAllParam.getEndPrice());
            bqb1.must().add(rqb);
        }
        RangeQueryBuilder rqb1 = new RangeQueryBuilder("minPrice");
        if (searchAllParam.getStartPrice() != null) {
            rqb1.gte(searchAllParam.getStartPrice());
            bqb1.must().add(rqb1);
        }
        if (searchAllParam.getEndPrice() != null) {
            rqb1.lte(searchAllParam.getEndPrice());
            bqb1.must().add(rqb1);
        }

        nsqb.withQuery(bqb1);
        //分页
        nsqb.withPageable(PageRequest.of(searchAllParam.getIndexPage() - 1, searchAllParam.getPageSize()));
        NativeSearchQuery nsq = nsqb.build();
        SearchHits<SpuEsModel> sh = eo.search(nsq, SpuEsModel.class);
        List<SpuEsModelDto> bds = sh.getSearchHits().stream().map(searchhit -> {
            SpuEsModelDto spuEsModelDto = BeanUtil.copyProperties(searchhit.getContent(), SpuEsModelDto.class);
            return spuEsModelDto;
        }).collect(Collectors.toList());
        PageSpuEsDto esDto = new PageSpuEsDto();
        esDto.setTotal(sh.getTotalHits());
        esDto.setSpuEsList(bds);
        return Result.getInstance(PageSpuEsDto.class).setData(esDto).setCode(200).setMsg("搜索成功");
    }

    @Override
    public PageCrowdProductDto pageListProductCrowd(ListCrowdProductForm listCrowdProductForm) {
        QueryWrapper<Spu> wrapper = new QueryWrapper<>();
        wrapper.eq("spu_type", listCrowdProductForm.getSpuType());
        wrapper.ne("spu_status", "DELETE");

        if (listCrowdProductForm.getKeyword() != null && !listCrowdProductForm.getKeyword().trim().equals("")) {
            wrapper.and(q -> q.like("spu_name", listCrowdProductForm.getKeyword()).or()
                    .like("category_name", listCrowdProductForm.getKeyword()).or()
                    .like("introduction", listCrowdProductForm.getKeyword()));
        }
        IPage<Spu> page = page(new Page<Spu>(listCrowdProductForm.getIndexPage(), listCrowdProductForm.getPageSize()), wrapper);
        PageCrowdProductDto pageCrowdProductDto = new PageCrowdProductDto();
        pageCrowdProductDto.setSpuDtoList(BeanUtil.copyToList(page.getRecords(), SpuDto.class));
        pageCrowdProductDto.setTotal(page.getTotal());
        pageCrowdProductDto.setIndexPage(page.getCurrent());
        return pageCrowdProductDto;
    }









}
